/*!
 * Block game
 * Code at: http://code.google.com/p/js-block-game/
 * version 1.2 (20-December-2012)
 * Licensed under the MIT license:
 * http://www.opensource.org/licenses/mit-license.php
 */
;
(function(window) {
    var gameBoard;
    var images = {};
    var toDelete;
    var level = 1;
    var score = 0;
    
    window.blockGame = function(_parent, _path) {
    	var sources = {
        	0: _path + 'img/0.png',
        	1: _path + 'img/1.png',
        	2: _path + 'img/2.png',
        	3: _path + 'img/3.png',
        	4: _path + 'img/4.png',
        	5: _path + 'img/5.png',
        	6: _path + 'img/6.png',
        	7: _path + 'img/7.png',
        	8: _path + 'img/8.png',
        	9: _path + 'img/9.png',
        	100: _path + 'img/100.png',
        	bomb: _path + 'img/bomb.png',
        	mag: _path + 'img/mag.png',
        	rock: _path + 'img/rock.png',
        	del: _path + 'img/del.png',
        	del0: _path + 'img/del0.png',
        	back0: _path + 'img/back0.png',
        	back1: _path + 'img/back1.png',
        	back2: _path + 'img/back2.png'
    	};
    
        _parent.style.position = 'relative';
        
        var background = document.createElement('canvas');
        background.setAttribute('width', '475px');
        background.setAttribute('height', '525px');
        _parent.appendChild(background);
        
        var menu = document.createElement('canvas');
        menu.setAttribute('width', '120px');
        menu.setAttribute('height', '200px');
        menu.style.position = 'absolute';
        menu.style.top = '95px';
        menu.style.left = '350px';
        _parent.appendChild(menu);
        
        var canvas = document.createElement('canvas');
        canvas.setAttribute('width', '312px');
        canvas.setAttribute('height', '382px');
        canvas.style.position = 'absolute';
        canvas.style.top = '95px';
        canvas.style.left = '30px';
        _parent.appendChild(canvas);
        
        var backContext = background.getContext('2d');
        var context = canvas.getContext('2d');
        var menuContext = menu.getContext('2d');
        
        loadImages(sources, function(img) {
            createGameBoard();
            drawBackground(backContext, img);
            drawStatistic(menuContext, level, score);
            drawGameBoard(context, img);
        });
        
        menu.addEventListener('click', function(evt) {
            var mousePos = getMousePos(menu, evt);
            var x = mousePos.x;
            var y = mousePos.y;
            if (x >= 0 && y >= 70 && x <= 120 && y <= 95) {
                level = 1;
                score = 0;
                createGameBoard();
                drawBackground(backContext, images);
                drawStatistic(menuContext, level, score);
                drawGameBoard(context, images);
            }
        });
        
        canvas.addEventListener('click', function(evt) {
            if (score < 10000) {
                var mousePos = getMousePos(canvas, evt);
                var x = mousePos.x;
                var y = mousePos.y;
                var j = Math.floor(y / 35);
                var i = Math.floor(x / 35);
                toDelete = new Array();
                if (gameBoard[i][j] == 'bomb') {
                    bombMagAction(i, j, true);
                }
                if (gameBoard[i][j] == 'mag') {
                    magAction(context, i, j);
                } else {
                    checkCrystal(i, j, gameBoard[i][j], {
                        i: i,
                        j: j,
                        p: gameBoard[i][j]
                    });
                }
                if (toDelete.length > 1) {
                    var toDeleteTemp = new Array();
                    toDeleteTemp.push(toDelete[0]);
                    for (var l = 0; l < toDelete.length; l++) {
                        var check = true;
                        for (var lt = 0; lt < toDeleteTemp.length; lt++) {
                            if (toDeleteTemp[lt].i == toDelete[l].i && toDeleteTemp[lt].j == toDelete[l].j) {
                                check = false;
                            }
                        }
                        if (check) {
                            toDeleteTemp.push(toDelete[l]);
                        }
                    }
                    for (var del in toDeleteTemp) {
                        if (gameBoard[toDeleteTemp[del].i][toDeleteTemp[del].j] != 'rock') {
                            gameBoard[toDeleteTemp[del].i][toDeleteTemp[del].j] = 'del';
                        } else {
                            gameBoard[toDeleteTemp[del].i][toDeleteTemp[del].j] = 'del0';
                        }
                    }
                    drawGameBoard(context, images);
                    setTimeout(function() {
                        var sc = 0;
                        for (var i = (gameBoard.length - 1); i >= 0; i--) {
                            for (var j = (gameBoard[i].length - 1); j >= 0; j--) {
                                if (gameBoard[i][j] == 'del' || gameBoard[i][j] == 'del_m') {
                                    sc++;
                                    for (var m = j; m >= 0; m--) {
                                        if (gameBoard[i][m].toString().indexOf('_m') == -1) {
                                            gameBoard[i][m] = gameBoard[i][m] + '_m';
                                        }
                                    }
                                    gameBoard[i].splice(j, 1);
                                }
                                if (gameBoard[i][j] == 'del0' || gameBoard[i][j] == 'del0_m') {
                                    for (var m = j; m >= 0; m--) {
                                        if (gameBoard[i][m].toString().indexOf('_m') == -1) {
                                            gameBoard[i][m] = gameBoard[i][m] + '_m';
                                        }
                                    }
                                    gameBoard[i].splice(j, 1);
                                }
                            }
                        }
                        score = score + (sc * 2);
                        var levelTemp = level;
                        level = (score / 1000 | 0) + 1;
                        if (levelTemp < level) {
                            drawBackground(backContext, images);
                        }
                        for (l = 0; l < gameBoard.length; l++) {
                            if (gameBoard[l].length < 11) {
                                var tempL = 11 - gameBoard[l].length;
                                var levelFixMax;
                                if (level > 9) {
                                    levelFixMax = 9;
                                } else {
                                    levelFixMax = level;
                                }
                                for (var l1 = 0; l1 < tempL; l1++) {
                                    var elem = random(1 + levelFixMax);
                                    var specElem = random(100);
                                    if (specElem == 70) {
                                        if (random(2) == 1) {
                                            elem = 'bomb';
                                        } else {
                                            elem = 'mag';
                                        }
                                    } else if (specElem == 50) {
                                        elem = 'rock';
                                    }
                                    gameBoard[l].unshift(elem + '_m');
                                }
                                drawOneColumn(context, images, l, true);
                                (function(l) {
                                    setTimeout(function() {
                                        drawOneColumn(context, images, l, false);
                                    }, 50);
                                })(l);
                            }
                        }
                        drawStatistic(menuContext, level, score);
                    }, 200);
                    setTimeout(function() {
                        var isEnd = true;
                        for (var it = 0; it < gameBoard.length - 1; it++) {
                            for (var jt = 0; jt < gameBoard[it].length - 1; jt++) {
                                if (gameBoard[it][jt] == 'mag') {
                                    isEnd = false;
                                    break;
                                }
                                if (gameBoard[it][jt] == 'bomb') {
                                    isEnd = false;
                                    break;
                                }
                                if (gameBoard[it][jt] == gameBoard[it + 1][jt]) {
                                    isEnd = false;
                                    break;
                                }
                                if (gameBoard[it][jt] == gameBoard[it][jt + 1]) {
                                    isEnd = false;
                                    break;
                                }
                            }
                        }
                        if (isEnd) {
                            drawGameText(backContext, 'Game over');
                        }
                    }, 1000);
                }
            } else {
                drawGameText(backContext, 'You Win!');
            }
        });
    }
    
    function checkCrystal(i, j, p, obj) {
        var check = true;
        if (toDelete.length > 0) {
            for (var l = 0; l < toDelete.length; l++) {
                if (toDelete[l].i == i && toDelete[l].j == j) {
                    check = false;
                }
            }
        }
        toDelete.push(obj);
        if (check) {
            if (i > 0) {
                if (p == gameBoard[(i - 1)][j]) {
                    checkCrystal(i - 1, j, gameBoard[(i - 1)][j], {
                        i: (i - 1),
                        j: j,
                        p: gameBoard[(i - 1)][j]
                    });
                }
            }
            if (i < 8) {
                if (p == gameBoard[(i + 1)][j]) {
                    checkCrystal(i + 1, j, gameBoard[(i + 1)][j], {
                        i: (i + 1),
                        j: j,
                        p: gameBoard[(i + 1)][j]
                    });
                }
            }
            if (j > 0) {
                if (p == gameBoard[i][(j - 1)]) {
                    checkCrystal(i, (j - 1), gameBoard[i][j - 1], {
                        i: i,
                        j: (j - 1),
                        p: gameBoard[i][(j - 1)]
                    });
                }
            }
            if (j < 10) {
                if (p == gameBoard[i][(j + 1)]) {
                    checkCrystal(i, (j + 1), gameBoard[i][(j + 1)], {
                        i: i,
                        j: (j + 1),
                        p: gameBoard[i][(j + 1)]
                    });
                }
            }
        }
    }
    
    function bombMagAction(i, j, isBomb) {
        for (var iP = -1; iP < 2; iP++) {
            for (var jP = -1; jP < 2; jP++) {
                var iC = i + iP;
                var jC = j + jP;
                if (iC != -1 && jC != -1) {
                    if (iC < 9 && jC < 11) {
                        if (isBomb) {
                            var obj = {
                                i: iC,
                                j: jC,
                                p: 'bomb'
                            }
                            toDelete.push(obj);
                        } else {
                            gameBoard[iC][jC] = 100;
                        }
                    }
                }
            }
        }
    }
    
    function magAction(context, i, j) {
        switch(random(3)) {
            case 0:
                bombMagAction(i, j, false);
                break;
            case 1:
                gameBoard[i][j] = 100;
                if (i != 0) {
                    gameBoard[i - 1][j] = 100;
                }
                if (j != 0) {
                    gameBoard[i][j - 1] = 100;
                }
                if (i != 8) {
                    gameBoard[i + 1][j] = 100;
                }
                if (j != 10) {
                    gameBoard[i][j + 1] = 100;
                }
                break;
            case 2:
                gameBoard[i][j] = 100;
                if (i != 0 && j != 0) {
                    gameBoard[i - 1][j - 1] = 100;
                }
                if (i != 8 && j != 10) {
                    gameBoard[i + 1][j + 1] = 100;
                }
                if (i != 0 && j != 10) {
                    gameBoard[i - 1][j + 1] = 100;
                }
                if (i != 8 && j != 0) {
                    gameBoard[i + 1][j - 1] = 100;
                }
                break;
        }
        drawGameBoard(context, images);
        
    }
    
    function drawGameBoard(context, img) {
        for (var i = 0; i < gameBoard.length; i++) {
            drawOneColumn(context, img, i, false);
        }
    }
    
    function drawOneColumn(context, img, i, first) {
        for (var j = 0; j < gameBoard[i].length; j++) {
            context.clearRect(35 * i, 35 * j, 35, 35);
            if (gameBoard[i][j].toString().indexOf('_m') == -1) {
                context.drawImage(img[gameBoard[i][j]], 35 * i, 35 * j);
            } else {
                if (first) {
                    context.drawImage(img[gameBoard[i][j].split('_')[0]], 35 * i, (35 * j) - 20);
                } else {
                    context.drawImage(img[gameBoard[i][j].split('_')[0]], 35 * i, 35 * j);
                    gameBoard[i][j] = gameBoard[i][j].split('_')[0];
                }
            }
        }
    }
    
    function drawStatistic(context, level, score) {
        context.clearRect(0, 0, 120, 200);
        context.rect(0, 0, 120, 60);
        context.rect(0, 70, 120, 25);
        context.fillStyle = 'rgba(0, 0, 0, 0.5)';
        context.fill();
        context.lineWidth = 1;
        context.strokeStyle = 'black';
        context.stroke();
        context.fillStyle = '#ffffff';
        context.font = 'italic bold 15px sans-serif';
        context.textBaseline = 'bottom';
        context.fillText('Level  ' + level, 5, 25);
        context.fillText('Score', 5, 50);
        context.fillText('New game', 20, 90);
        context.font = '12px sans-serif';
        context.fillText(score, 55, 50);
    }
    
    function drawBackground(context, images) {
        var img = 'back' + random(3);
        context.drawImage(images[img], 0, 0);
    }
    
    function drawGameText(context, text) {
        context.fillStyle = '#f00';
        context.font = 'italic bold 40px sans-serif';
        context.textBaseline = 'bottom';
        context.fillText(text, 100, 80);
    }
    
    function createGameBoard() {
        gameBoard = new Array();
        for (var i = 0; i < 9; i++) {
            gameBoard[i] = new Array();
            for (var j = 0; j < 11; j++) {
                gameBoard[i][j] = random(2);
            }
        }
    }
    
    function loadImages(sources, callback) {
        var loadedImages = 0;
        var numImages = 0;
        
        for (var src in sources) {
            numImages++;
        }
        for (var src in sources) {
            images[src] = new Image();
            images[src].onload = function() {
                if (++loadedImages >= numImages) {
                    callback(images);
                }
            };
            images[src].src = sources[src];
        }
    }
    
    function random(t) {
        return Math.floor(Math.random() * t);
    }
    
    function getMousePos(canvas, evt){
        var obj = canvas;
        var top = 0;
        var left = 0;
        while (obj.tagName != 'BODY') {
            top += obj.offsetTop;
            left += obj.offsetLeft;
            obj = obj.offsetParent;
        }
 
        var mouseX = evt.clientX - left + window.pageXOffset;
        var mouseY = evt.clientY - top + window.pageYOffset;
        return  {
            x: mouseX,
            y: mouseY
        };
    }
})(window);
